<template>
  <div ref="myChart" :class="className" :style="{ height: height, width: width, }"></div>
</template>
<script>
import * as echarts from "echarts";
import "echarts-gl";
export default {
  props: {
    className: { type: String, default: "container" },
    width: { type: String, default: "100%" },
    height: { type: String, default: "400px" },
    datalist: {
      type: Array,
      default: () => [
        { name: "博士", value: 1.1, itemStyle: { color: "#4A90E2" } },
        { name: "硕士", value: 40.35, itemStyle: { color: "#FF7D00" } },
        { name: "本科", value: 73.64, itemStyle: { color: "#8C8C8C" } },
      ],
    },
    instanceKey: {
      type: String,
      default: () => `pie3d-${Date.now()}-${Math.floor(Math.random() * 1000)}`
    }
  },
  data() {
    return { chart: null, scale: 1, totalValue: 0 };
  },
  watch: { datalist: { handler: "initChart", deep: true } },
  mounted() {
    this.initChart();
    window.addEventListener("resize", () => this.chart?.resize());
  },
  beforeUnmount() {
    window.removeEventListener("resize", () => this.chart?.resize());
  },
  methods: {
    initChart() {
      const that = this;
      // 基础缩放比例（确保字体清晰）
      that.scale = Math.max(window.devicePixelRatio / 2, 1);
      const myChart = echarts.init(this.$refs.myChart);
      this.chart = myChart;
      const data = this.datalist;
      that.totalValue = data.reduce((sum, item) => sum + item.value, 0);

      // 生成扇形曲面参数方程（固定高度，避免过高遮挡标签）
      function getParametricEquation(startRatio, endRatio, isSelected, isHovered) {
        const midRatio = (startRatio + endRatio) / 2;
        const startRadian = startRatio * Math.PI * 2;
        const endRadian = endRatio * Math.PI * 2;
        const midRadian = midRatio * Math.PI * 2;
        if (startRatio === 0 && endRatio === 1) isSelected = false;

        // 选中/hover状态的偏移量
        const offsetX = isSelected ? Math.cos(midRadian) * 0.05 : 0;
        const offsetY = isSelected ? Math.sin(midRadian) * 0.05 : 0;
        const hoverRate = isHovered ? 1.03 : 1;

        return {
          u: { min: -Math.PI, max: Math.PI * 3, step: Math.PI / 32 },
          v: { min: 0, max: Math.PI * 2, step: Math.PI / 20 },
          x: function (u, v) {
            if (u < startRadian) return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * 0.5) * hoverRate;
            if (u > endRadian) return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * 0.5) * hoverRate;
            return offsetX + Math.cos(u) * (1 + Math.cos(v) * 0.5) * hoverRate;
          },
          y: function (u, v) {
            if (u < startRadian) return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * 0.5) * hoverRate;
            if (u > endRadian) return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * 0.5) * hoverRate;
            return offsetY + Math.sin(u) * (1 + Math.cos(v) * 0.5) * hoverRate;
          },
          z: function (u, v) {
            // 降低扇形高度，避免遮挡标签
            const fixedHeight = 0.1;
            return Math.sin(v) > 0 ? fixedHeight : -0.1;
          },
        };
      }

      // 生成3D饼图配置
      function getPie3D(pieData) {
        const series = [];
        let sumValue = 0;
        let startValue = 0;
        let endValue = 0;
        const legendData = [];

        // 初始化扇形数据
        pieData.forEach(item => {
          sumValue += item.value;
          series.push({
            name: item.name,
            type: "surface",
            parametric: true,
            wireframe: { show: false },
            itemStyle: item.itemStyle || {},
            pieData: { ...item, startRatio: 0, endRatio: 0 },
            pieStatus: { selected: false, hovered: false }
          });
          legendData.push(item.name);
        });

        // 计算每个扇形的角度范围
        series.forEach((item, index) => {
          endValue = startValue + item.pieData.value;
          item.pieData.startRatio = startValue / sumValue;
          item.pieData.endRatio = endValue / sumValue;
          item.parametricEquation = getParametricEquation(
            item.pieData.startRatio,
            item.pieData.endRatio,
            false,
            false
          );
          startValue = endValue;
        });

        // ########### 百分比标签核心配置 ###########
        series.push({
          type: "scatter3D", // 使用scatter3D确保在3D空间正确渲染
          coordinateSystem: "cartesian3D", // 绑定3D坐标系
          symbolSize: 0, // 隐藏点标记
          label: {
            show: true,
            position: "top",
            color: "#FFFFFF", // 白色文字，确保与深色背景对比
            fontSize: 16 * that.scale, // 字体适中
            fontWeight: "bold",
            formatter: params => params.name,
            // 强制显示标签（关键）
            hideOverlap: false
          },
          data: pieData.map((item, index) => {
            const startRatio = series[index].pieData.startRatio;
            const endRatio = series[index].pieData.endRatio;
            const midRatio = (startRatio + endRatio) / 2; // 扇形中间角度比例
            const radian = midRatio * Math.PI * 2; // 转换为弧度

            // 标签位置：在扇形外侧上方（半径1.1倍，上移0.1）
            const radius = 1.1;
            return {
              name: ((item.value / that.totalValue) * 100).toFixed(2) + "%",
              // 3D坐标（x,y,z）：z设为0.3确保在扇形上方
              value: [
                Math.cos(radian) * radius, // x坐标
                Math.sin(radian) * radius - 0.1, // y坐标（上移0.1）
                0.3 // z坐标（高于扇形高度0.2）
              ]
            };
          })
        });

        // 辅助交互层（不显示，用于鼠标事件）
        series.push({
          name: "mouseoutSeries",
          type: "pie",
          labelLine: { show: false },
          tooltip: { show: false },
          label: { show: false },
          radius: ["80%", "100%"],
          center: ["50%", "50%"],
          itemStyle: { opacity: 0 },
          data: data,
        });

        return {
          // 3D坐标系配置（扩大范围避免标签被裁）
          xAxis3D: {
            min: -1.5,
            max: 1.5,
            show: false
          },
          yAxis3D: {
            min: -1.5,
            max: 1.5,
            show: false
          },
          zAxis3D: {
            min: -0.5,
            max: 0.5,
            show: false
          },
          grid3D: {
            show: false,
            viewControl: {
              alpha: 30, // 视角倾斜度
              beta: 45, // 视角旋转度
              distance: 200, // 观察距离
              // 禁用旋转/缩放，避免视角错乱
              rotateSensitivity: 0,
              zoomSensitivity: 0,
              panSensitivity: 0,
            },
            // 增强3D效果，确保标签可见
            postEffect: {
              enable: true,
              SSAO: { enable: true }
            }
          },
          legend: {
            data: legendData,
            bottom: 0,
            left: "center",
            itemGap: 20, // 保持之前的间距配置
            // 关键：配置文字样式，解决显示不全
            textStyle: {
              color: "#FFFFFF",
              fontSize: 20 * that.scale,
              // 自定义富文本样式，控制文字宽度和溢出
              rich: {
                // 为文字设置最大宽度，超过则处理
                label: {
                  width: 80, // 最大宽度（根据实际文字长度调整，如“博士”较短，可设小些）
                  overflow: "break", // 超过宽度自动换行（可选：'ellipsis' 显示省略号）
                  lineHeight: 20, // 若换行，设置行高避免重叠
                }
              }
            },
          },
          tooltip: {
            formatter: (params) => {
              if (params.seriesName !== "mouseoutSeries") {
                return `${params.seriesName}: ${((params.value[3] || 0) / sumValue * 100).toFixed(2)}%`;
              }
            }
          },
          series: series
        };
      }
      // 渲染图表
      const option = getPie3D(data);
      myChart.setOption(option);

      // 鼠标交互（保持扇形高亮效果）
      let hoveredIndex = -1;
      myChart.on("mouseover", (params) => {
        if (params.seriesName === "mouseoutSeries") {
          const index = params.dataIndex;
          if (index !== hoveredIndex) {
            // 重置上一个选中的扇形
            if (hoveredIndex !== -1) {
              option.series[hoveredIndex].parametricEquation = getParametricEquation(
                option.series[hoveredIndex].pieData.startRatio,
                option.series[hoveredIndex].pieData.endRatio,
                false,
                false
              );
            }
            // 高亮当前扇形
            option.series[index].parametricEquation = getParametricEquation(
              option.series[index].pieData.startRatio,
              option.series[index].pieData.endRatio,
              false,
              true
            );
            hoveredIndex = index;
            myChart.setOption(option);
          }
        }
      });

      // 鼠标离开时重置
      myChart.on("mouseout", () => {
        if (hoveredIndex !== -1) {
          option.series[hoveredIndex].parametricEquation = getParametricEquation(
            option.series[hoveredIndex].pieData.startRatio,
            option.series[hoveredIndex].pieData.endRatio,
            false,
            false
          );
          hoveredIndex = -1;
          myChart.setOption(option);
        }
      });
    }
  },
};
</script>

<style scoped>
.container {
  /* 确保图表容器不裁剪内容 */
  overflow: visible !important;
}

/* 强制tooltip样式 */
::v-deep .echarts-tooltip {
  background: rgba(0, 0, 0, 0.8) !important;
  color: white !important;
  border: none !important;
  padding: 6px 10px !important;
}
</style>